package org.spdata.tsdb.entity;

import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.bson.Document;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spdata.utils.ByteUtils;

public class Snapshot extends Entity<ObjectId>{
	private static Logger logger = LoggerFactory.getLogger(Snapshot.class);
	final static int maxSize = 1024*1024*15;
	public enum Type{
		full,
		addition,
		part;
	}
	private ObjectId id;
	private Date time;
	private int index;
	private ObjectId parent;
	private Type type;
	private byte[] data;
	private ByteArrayOutputStream output = null;
	
	@Override
	public Document toDocument() {
		Document doc = new Document();
		doc.append("type", type.toString());
		doc.append("data", this.getData());
		
		if(type.equals(Type.full) || type.equals(Type.addition)) {
			doc.append("time", this.time);
		}else {
			doc.append("index", index);
			doc.append("parent", parent);
		}
		return doc;
	}

	@Override
	public ObjectId getId() {
		return id;
	}

	@Override
	public void setId(ObjectId t) {
		this.id = t;
	}

	
	
	public Date getTime() {
		return time;
	}

	public void setTime(Date time) {
		this.time = time;
	}

	public int getIndex() {
		return index;
	}

	public void setIndex(int index) {
		this.index = index;
	}

	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = type;
	}
	

	public ObjectId getParent() {
		return parent;
	}

	public void setParent(ObjectId parent) {
		this.parent = parent;
	}

	public void writeData (byte[] bytes) throws Exception{
		if(output==null)
			output = new ByteArrayOutputStream();
	
		this.output.write(bytes);
	}
	
	public void writeData(byte[] bytes,int off ,int len)throws Exception{
		this.output.write(bytes, off, len);
	}
	
	
	public int restDataSize() {
		if(this.output==null)
			return maxSize;
		return maxSize - this.output.size();
	}

	public byte[] getData() {
		if(data==null) {
			if(output!=null)
				data = output.toByteArray();
		}
		return data;
	}

	public void setData(byte[] data) {
		this.data = data;
	}
	
	private int off = 0;
	public Map<String,Object> nextFramgment(){
		if(data.length>off) {
			Map<String,Object> f = new HashMap<String,Object>();
			int metricId = ByteUtils.changeBytesToInt(this.data[off],data[off+1],data[off+2],data[off+3]);
			int from = ByteUtils.changeBytesToInt(data[off+4],data[off+5]);
			int len = ByteUtils.changeBytesToInt(data[off+6],data[off+7]);
			byte[] bytes = new byte[len];
			System.arraycopy(data, off+8, bytes, 0, len);
			off = off+4+2+2+len;
			f.put("metricId", metricId);
			f.put("data", bytes);
			f.put("from", from);
			return f;
		}else
			return null;
	}

	@Override
	public String toString() {
		return "Snapshot [id=" + id + ", time=" + time + ", index=" + index + ", parent=" + parent + ", type=" + type
				+ "]";
	}
	
	
}
